/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012-2013 Oliver Katz */

#ifndef __COMMON_DATA_H
#define __COMMON_DATA_H

#include <stdio.h>
#include <malloc.h>
#include <string.h>

// if you change these, make sure to edit mod_codeserver.cpp - linkStandardLibrary()
#define Z_TYPEID_NULL 0 //valueof z_typeid: the data is untyped (will not cause any errors)
#define Z_TYPEID_INT 1 //valueof z_typeid: the data is referencing an integer
#define Z_TYPEID_STR 2 //valueof z_typeid: the data is referencing a string
#define Z_TYPEID_VECTOR 3 //valueof z_typeid: the data is referencing a vector
#define Z_TYPEID_ASSOC 4 //valueof z_typeid: the data is referencing an associative array
#define Z_TYPEID_PAIR 5 //valueof z_typeid: the data is referencing a pair

#define Z_WARNING_DATA(d, r) Z_WARNING_NULL(d, r);if((d)->src==NULL){Z_WARNING("cannot operate on null data: %s", #d);return r;}

//type z_typeid: a type identification number
typedef unsigned int z_typeid;
extern z_typeid z_typeid_null;

//type z_size: size of data in bytes
typedef unsigned int z_size;
extern z_size z_size_empty;

//struct z_data: a structure for referencing blocks of loosely-typed data
typedef struct
{
	z_typeid tid; //memberof z_data: the type identification number of the referenced data
	z_size size; //memberof z_data: the size (in bytes) of the data
	void *src; //memberof z_data: the address of the memory
} z_data;

//argof z_data_init: z_typeid t: the type of the data reference
//argof z_data_init: z_size s: the size of the data block referenced
z_data z_data_init(z_typeid t, z_size s); //methodof z_data: initializer
z_data *z_data_new(z_typeid t, z_size s); //methodof z_data: allocator
int z_data_release(z_data d); //methodof z_data: frees (using zfree/zalloc) the data referenced within 'd'
int z_data_delete(z_data *d); //methodof z_data: same as z_data_release, but also deletes the z_data object
z_typeid z_data_typeid_get(z_data *d); //methodof z_data:
z_typeid z_data_typeid_set(z_data *d, z_typeid t); //methodof z_data:
z_size z_data_size_get(z_data *d); //methodof z_data:
z_size z_data_size_set(z_data *d, z_size s); //methodof z_data:
void *z_data_src_get(z_data *d); //methodof z_data:
void *z_data_src_set(z_data *d, void *s); //methodof z_data:
int z_data_retrieve_query_code(z_data *d); //methodof z_data: overwrites all data with a single integer (query code) - used for IPC
int z_data_assign_query_code(z_data *d, int c); //methodof z_data: retrieves the query code - used for IPC
//returnof z_data_eq: int: returns 1 if they are equal, otherwise 0
int z_data_eq(z_data *a, z_data *b); //methodof z_data: compares 'a' and 'b'
//returnof z_data_null: int: returns 1 if 'd' is null (this can be achieved by z_data_init(0, 0)), otherwise 0
int z_data_null(z_data *d); //methodof z_data: checks to see if 'd' is null
z_data z_data_wrap(void *ptr, z_typeid t, z_size s); //methodof z_data: wraps 'ptr' in a z_data
z_data *_z_data_wrap(void *ptr, z_typeid t, z_size s);

/// z_data is a structure for wrapping data. It's similar to shared_ptr<> in c++. It is created as a reference to an existing memory block, but then frees the memory block once it itself is deleted.
/// 
/// For example:
/// {{char *text = "this string needs to be sent to another process inside a z_data\n";
/// z_data data = z_data_wrap(text, strlen(text)*sizeof(char));
/// // now that it is encapsulated, we need to get the string out of there (resuce mission time)
/// char *rescuee = (char *)z_data_src_get(&data);
/// printf("%s\n", rescuee); // this will print the contents of 'text'}}

#endif
